#pragma once
#include<iostream>
#include<memory>
#include<sys/wait.h>
#include"Socket.hpp"

using tcphandle_t = std::function<bool(SockPtr,struct sockaddr*)>;
class TcpServer{
    public:
        TcpServer(int port)
            :_port(port)
            ,_is_running(false)
            ,_listen_socket(std::make_unique<TcpSocket>())//在智能指针中将基类指向子类
        {}
        void InitServer(tcphandle_t tcp_handle)
        {
            _tcp_handle = tcp_handle;//传递上层调用方法
            _listen_socket->Build_Socket(_port);
        }
        void Loop()
        {
            _is_running = true;
            while(_is_running){
                //1.接收客户端连接请求
                struct sockaddr_in client_addr;//定义客户端地址结构体
                auto conn_socket = _listen_socket->Accept((struct sockaddr*)&client_addr);//封装之后返回的是智能指针对象
                if(conn_socket==nullptr)
                    continue;
                //获取客户端IP地址和端口号
                uint16_t client_port = ::ntohs(client_addr.sin_port);
                char buffer[64];
                std::string client_ip = ::inet_ntop(AF_INET,&client_addr.sin_addr,buffer,sizeof(buffer));//将IP地址转换为字符串
                LOG(log_level::INFO)<<"Accept client from " << client_ip << ":" << client_port;
                //2.I/O操作
                pid_t id = fork();
                if(id==0){//子进程
                    _listen_socket->Close();
                    if(fork()>0) exit(0);//子进程退出
                    //孙子进程成为孤儿，处理上层方法
                    _tcp_handle(conn_socket,(struct sockaddr*)&client_addr);//读取发送交给上层处理
                    exit(0);
                }
                conn_socket->Close();//连接的文件描述符交给了子进程，父进程回收这个描述符
                waitpid(id,nullptr,0);//回收退出的子进程
            }
            _is_running  = false;
        }
        ~TcpServer()
        {
            _listen_socket->Close();
        }
    private:
        std::unique_ptr<Socket> _listen_socket;
        bool _is_running;
        int _port;

        tcphandle_t _tcp_handle;//回调函数
};